import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.*;

//此为改进后的代码
public class WF {

    public static void main(String[] args) {
        if (args.length != 2 || !args[0].equals("-c")) {
            System.out.println("Usage: java WF -c <file name>");
            System.out.println("Example: java WF -c gone_with_the_wind.txt");
            return;
        }

        String fileName = args[1];
        try {
            long startTime = System.currentTimeMillis();
            analyzeLetterFrequencyOptimized(fileName);
            long endTime = System.currentTimeMillis();
            System.out.printf("\nProcessing completed in %d ms\n", endTime - startTime);
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
            System.out.println("Please check if the file exists and is accessible.");
        } catch (OutOfMemoryError e) {
            System.out.println("Error: File is too large to process. Please use a smaller file or increase JVM memory.");
        } catch (Exception e) {
            System.out.println("Unexpected error: " + e.getMessage());
        }
    }

    private static void analyzeLetterFrequencyOptimized(String fileName) throws IOException {
        // 使用数组而不是Map，O(1)访问时间
        int[] letterCounts = new int[26];
        int totalLetters = 0;
        long totalChars = 0;

        System.out.println("Analyzing letter frequency for: " + fileName);
        System.out.println("Reading file...");

        // 使用带缓冲的读取器，减少IO操作
        try (InputStreamReader isr = new InputStreamReader(
                new FileInputStream(fileName), StandardCharsets.UTF_8);
             BufferedReader reader = new BufferedReader(isr, 64 * 1024)) { // 64KB缓冲区

            char[] buffer = new char[32 * 1024]; // 32KB字符缓冲区
            int charsRead;

            while ((charsRead = reader.read(buffer)) != -1) {
                totalChars += charsRead;
                processBuffer(buffer, charsRead, letterCounts);
                totalLetters += countLettersInBuffer(buffer, charsRead);

                if (totalChars % (1024 * 1024) == 0) {
                    System.out.printf("Processed: %.1f MB\n", totalChars / (1024.0 * 1024.0));
                }
            }
        }

        // 验证数据有效性
        if (totalLetters == 0) {
            System.out.println("Warning: No English letters found in the file.");
            return;
        }

        // 生成并排序结果
        System.out.println("Generating results...");
        List<LetterInfo> results = buildAndSortResults(letterCounts, totalLetters);

        // 输出结果
        printResults(results, totalLetters, totalChars);
    }

    private static void processBuffer(char[] buffer, int length, int[] letterCounts) {
        for (int i = 0; i < length; i++) {
            char c = buffer[i];

            // 快速检查是否为字母（避免函数调用）
            if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                // 使用位运算统一转为小写索引
                // 0x20 是大小写字母的ASCII差值，通过位与操作实现快速转换
                int index = (c | 0x20) - 'a';
                if (index >= 0 && index < 26) {
                    letterCounts[index]++;
                }
            }
        }
    }

    private static int countLettersInBuffer(char[] buffer, int length) {
        int count = 0;
        for (int i = 0; i < length; i++) {
            char c = buffer[i];
            if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                count++;
            }
        }
        return count;
    }

    private static List<LetterInfo> buildAndSortResults(int[] letterCounts, int totalLetters) {
        List<LetterInfo> results = new ArrayList<>(26);

        for (int i = 0; i < 26; i++) {
            char letter = (char) ('a' + i);
            int count = letterCounts[i];
            double percentage = (count * 100.0) / totalLetters;
            results.add(new LetterInfo(letter, count, percentage));
        }

        // 排序：频率降序，频率相同按字典序
        results.sort((a, b) -> {
            // 使用Double.compare确保浮点数比较的准确性
            int freqCompare = Double.compare(b.percentage, a.percentage);
            if (freqCompare != 0) {
                return freqCompare;
            }
            // 频率相同，按字母顺序排列
            return Character.compare(a.letter, b.letter);
        });

        return results;
    }

    private static void printResults(List<LetterInfo> results, int totalLetters, long totalChars) {
        DecimalFormat df = new DecimalFormat("0.00");
        DecimalFormat countFormat = new DecimalFormat("#,###");

        System.out.println("\n" + "=".repeat(50));
        System.out.println("LETTER FREQUENCY ANALYSIS RESULTS");
        System.out.println("=".repeat(50));
        System.out.printf("Total characters processed: %s\n", countFormat.format(totalChars));
        System.out.printf("Total English letters: %s\n", countFormat.format(totalLetters));
        System.out.printf("Letter to total ratio: %.2f%%\n", (totalLetters * 100.0) / totalChars);
        System.out.println("-".repeat(50));

        // 表头
        System.out.printf("%-8s %-12s %-10s %-12s\n",
                "Rank", "Letter", "Count", "Percentage");
        System.out.println("-".repeat(50));

        // 输出每个字母的频率
        for (int i = 0; i < results.size(); i++) {
            LetterInfo info = results.get(i);
            System.out.printf("%-8d %-12c %-10s %-12s\n",
                    i + 1,
                    info.letter,
                    countFormat.format(info.count),
                    df.format(info.percentage) + "%");
        }

        System.out.println("-".repeat(50));

        // 输出最常见的5个字母和最不常见的5个字母
        System.out.println("\nTop 5 most frequent letters:");
        for (int i = 0; i < Math.min(5, results.size()); i++) {
            LetterInfo info = results.get(i);
            System.out.printf("  %c: %s%%\n", info.letter, df.format(info.percentage));
        }

        System.out.println("\nTop 5 least frequent letters:");
        for (int i = Math.max(0, results.size() - 5); i < results.size(); i++) {
            LetterInfo info = results.get(i);
            System.out.printf("  %c: %s%%\n", info.letter, df.format(info.percentage));
        }
    }

    static class LetterInfo {
        final char letter;
        final int count;
        final double percentage;

        LetterInfo(char letter, int count, double percentage) {
            this.letter = letter;
            this.count = count;
            this.percentage = percentage;
        }
    }

    public static void performanceTest(String fileName) throws IOException {
        System.out.println("=== PERFORMANCE TEST ===");

        // 测试不同缓冲区大小的性能
        int[] bufferSizes = {4096, 8192, 16384, 32768, 65536};

        for (int bufferSize : bufferSizes) {
            long startTime = System.currentTimeMillis();

            int[] letterCounts = new int[26];
            int totalLetters = 0;

            try (BufferedReader reader = new BufferedReader(
                    new FileReader(fileName), bufferSize)) {

                char[] buffer = new char[bufferSize];
                int charsRead;

                while ((charsRead = reader.read(buffer)) != -1) {
                    for (int i = 0; i < charsRead; i++) {
                        char c = buffer[i];
                        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                            int index = (c | 0x20) - 'a';
                            letterCounts[index]++;
                            totalLetters++;
                        }
                    }
                }
            }

            long endTime = System.currentTimeMillis();
            System.out.printf("Buffer size: %6d - Time: %4d ms - Letters: %,d\n",
                    bufferSize, (endTime - startTime), totalLetters);
        }
    }
}